package top.wshape1.rpc.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import top.wshape1.rpc.common.constant.RpcFilterType;
import top.wshape1.rpc.config.JJRpcConfig;
import top.wshape1.rpc.filter.Filter;
import top.wshape1.rpc.filter.FilterChainFactory;
import top.wshape1.rpc.spring.annotation.JJService;
import top.wshape1.rpc.spring.annotation.RpcFilter;

/**
 * @author Wshape1
 * @version 1.0
 * @description
 * @since 2024-02-19
 */

@Slf4j
public class ProviderPostProcessor implements BeanPostProcessor, InitializingBean {
    @Override
    public void afterPropertiesSet() {
        JJRpcConfig.CONFIG.getProvider().setEnabled(true);
        Thread thread = new Thread(() -> {
            try {
                JJRPCHolder.getJJRPC().startProvider();
            } catch (Exception e) {
                log.error("Start Provider error: {}", e.getMessage(), e);
            }
        });
        thread.setDaemon(true);
        thread.start();
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        Class<?> clazz = bean.getClass();
        JJService annotation = clazz.getAnnotation(JJService.class);

        if (annotation != null) {
            Class<?>[] interfaces = clazz.getInterfaces();
            if (interfaces.length == 0) {
                log.error("No interface found in class: {}, cancel register.", clazz.getName());
                throw new RuntimeException("No interface found in class: " + clazz.getName());
            }
            Class<?> serviceInterface = annotation.value();
            if (serviceInterface.isInterface()) {
                // 指定接口, 检查是否实现这一接口
                boolean flag = false;
                for (Class<?> i : interfaces) {
                    if (i.isAssignableFrom(serviceInterface)) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    log.error("The specified interface {} is not implemented.", serviceInterface.getName());
                    throw new RuntimeException("The specified interface " + serviceInterface.getName() + " is not implemented.");
                }
            } else {
                // 获取实现接口的第一个
                serviceInterface = interfaces[0];
            }

            // 注册服务
            JJRPCHolder.getJJRPC().registerService((Class<Object>) serviceInterface, bean);

        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        // RpcFilter注解
        if (bean instanceof Filter) {
            RpcFilter annotation = bean.getClass().getAnnotation(RpcFilter.class);
            if (annotation != null) {
                for (RpcFilterType rpcFilterType : annotation.value()) {
                    if (rpcFilterType == RpcFilterType.PROVIDER_SEND_RESPONSE) {
                        FilterChainFactory.getProviderSendRespFilterChain().addFilter((Filter) bean);
                    } else if (rpcFilterType == RpcFilterType.PROVIDER_RECEIVE_REQUEST) {
                        FilterChainFactory.getProviderRecReqFilterChain().addFilter((Filter) bean);
                    }
                }

            }
        }

        return bean;
    }
}
